package config

import (
	"etcd/data"
	"fmt"
	"gopkg.in/yaml.v2"
	"os"
	"sync"
	"time"
)

//配置结构体
type Config struct {
	Filename       string        //配置文件名称
	LastModifyTime int64         //记录配置文件上一次更改时间
	Lock           *sync.RWMutex //读写锁
	Data           *Yml          //配置项数据
	notifyList     []Notifyer    //存放所有观察者，此处我们用到了观察者模式，也就是需要用到这个配置的对象，我们就把它加到这个切片。当配置更新之后，通知切片中的对象配置更新了。
}

//观察者
type Notifyer interface {
	Callback(*Config)
}

//初始化配置
func NewConfig(filename string) (conf *Config, err error) {
	conf = &Config{
		Filename: filename,
		Data:     &Yml{},
		Lock:     &sync.RWMutex{},
	}
	_, err = conf.parse()
	if err != nil {
		return nil, err
	}
	return
}

//添加观察者
func (c *Config) AddObserver(n Notifyer) {
	c.notifyList = append(c.notifyList, n)
}

//解析配置
func (c *Config) parse() (bool, error) {
	//记录最后修改时间
	//fileInfo, _ := os.Stat(c.Filename)
	//c.LastModifyTime = fileInfo.ModTime().Unix()

	bytesContent, err := data.Asset(c.Filename)
	if err != nil {
		fmt.Println(err.Error())
		return false, err
	}
	c.Lock.Lock()
	err = yaml.Unmarshal(bytesContent, c.Data)
	c.Lock.Unlock()
	if err != nil {
		fmt.Println(err.Error())
		return false, err
	}
	return true, nil
}

//重载配置
func (c *Config) reload() {
	ticker := time.NewTicker(time.Second * 5)
	for _ = range ticker.C {
		func() {
			fileInfo, _ := os.Stat(c.Filename)
			currModifyTime := fileInfo.ModTime().Unix()
			if currModifyTime > c.LastModifyTime {
				if res, err := c.parse(); res {
					fmt.Printf("重新加载配置文件: %v, 配置项：%v \n", c.Filename, c.Data)
					// 配置更新通知所有观察者
					for _, n := range c.notifyList {
						n.Callback(c)
					}
				} else {
					fmt.Printf("重新加载配置失败，错误信息：%v", err)
				}
			}
		}()
	}
}

//重载配置-etcd
func (c *Config) UpdataConfFromEtcd() {

}
